<!-- 表单组件 -->
<script setup lang="ts">
import { ref, type PropType, onMounted } from 'vue'
import MuiFormItem from './DuiFormItem.vue'
import type { IMyFormItem } from '@/types/global'

defineProps({
  // 表单文字宽度
  labelWidth: {
    type: String,
    default: '120px'
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 尺码
  size: {
    type: String,
    default: 'default'
  },
  // 表单配置
  formConfig: {
    type: Array as PropType<IMyFormItem[]>,
    default() {
      return []
    }
  },
  // 表单数据
  formData: {
    type: Object as PropType<any>,
    default() {
      return {}
    }
  }
})

// 表单实例
const ruleFormRef = ref()

/**
 * 验证数据
 */
function validate() {
  return new Promise((resolve, reject) => {
    if (!ruleFormRef.value) {
      reject()
    }
    ruleFormRef.value.validate((valid: any, fields: any) => {
      if (valid) {
        resolve(valid)
      } else {
        reject(fields)
      }
    })
  })
}

onMounted(() => {
  // 清空初始就有的错误信息
  setTimeout(() => {
    ruleFormRef.value?.clearValidate()
  }, 0)
})

defineExpose({
  validate
})
</script>

<template>
  <ElForm
    ref="ruleFormRef"
    label-position="right"
    label-suffix=":"
    :label-width="labelWidth"
    :model="formData"
    :disabled="disabled"
    :size="size"
    style="overflow: hidden"
  >
    <ElRow :gutter="40">
      <ElCol v-for="item in formConfig" :key="item.prop" :span="item.span || 24">
        <!-- 标题 -->
        <template v-if="item.type === 'title'">
          <div>{{ item.label }}</div>
        </template>
        <!-- 其他 -->
        <template v-else>
          <MuiFormItem
            v-if="!item.hide"
            :label="item.label"
            :prop="item.prop"
            :required="item.required"
            :tip="item.tip"
            :rules="item.rules || []"
          >
            <!-- 插槽 -->
            <template v-if="item.type === 'slot'">
              <slot :name="`${item.prop}Slot`"></slot>
            </template>
            <!-- 文字 -->
            <div v-if="item.type == 'text'">{{ formData[item.prop] }}</div>
            <!-- input -->
            <template v-else-if="item.type == 'input'">
              <el-input
                v-model="formData[item.prop]"
                :placeholder="`请输入${item.label}`"
                clearable
                :disabled="item.disabled"
                @change="item.change"
                v-bind="item.options || {}"
              />
            </template>
            <!-- number -->
            <template v-else-if="item.type == 'number'">
              <el-input-number
                v-model="formData[item.prop]"
                :min="0"
                :disabled="item.disabled"
                @change="item.change"
                v-bind="item.options || {}"
              />
            </template>
            <!-- textarea -->
            <template v-else-if="item.type == 'textarea'">
              <el-input
                v-model="formData[item.prop]"
                :rows="4"
                type="textarea"
                resize="none"
                :placeholder="`请输入${item.label}`"
                clearable
                :disabled="item.disabled"
                @change="item.change"
                v-bind="item.options || {}"
              />
            </template>
            <!-- select -->
            <template v-else-if="item.type == 'select'">
              <el-select
                v-model="formData[item.prop]"
                :placeholder="`请选择${item.label}`"
                clearable
                filterable
                :disabled="item.disabled"
                @change="item.change"
                v-bind="item.options || {}"
                style="width: 100%"
              >
                <el-option
                  v-for="listItem in item.list || []"
                  :key="listItem.label"
                  :label="listItem.label"
                  :value="listItem.value"
                />
              </el-select>
            </template>
            <!-- tree -->
            <template v-else-if="item.type == 'tree'">
              <el-tree-select
                v-model="formData[item.prop]"
                :data="item.list"
                show-checkbox
                :render-after-expand="false"
                :disabled="item.disabled"
                @change="item.change"
                v-bind="item.options || {}"
                style="width: 100%"
              />
            </template>
            <!-- radio -->
            <template v-else-if="item.type == 'radio'">
              <el-radio-group
                v-model="formData[item.prop]"
                :disabled="item.disabled"
                v-bind="item.options || {}"
                @change="item.change"
              >
                <el-radio :label="listItem.value" v-for="listItem in item.list || []" :key="listItem.label">
                  {{ listItem.label }}
                </el-radio>
              </el-radio-group>
            </template>
            <!-- date -->
            <template v-else-if="item.type == 'date'">
              <el-date-picker
                @change="item.change"
                v-model="formData[item.prop]"
                type="datetime"
                :placeholder="`请选择${item.label}`"
                value-format="YYYY-MM-DD HH:mm:ss"
                :disabled="item.disabled"
                v-bind="item.options || {}"
              />
            </template>
            <!-- 自定义组件 -->
            <template v-else>
              <component
                :is="item.type"
                v-model="formData[item.prop]"
                @change="item.change"
                v-bind="item.options"
                :disabled="disabled || item?.disabled"
              />
            </template>
          </MuiFormItem>
        </template>
      </ElCol>
    </ElRow>
  </ElForm>
</template>

<style lang="scss" scoped>
.db-form {
  width: 100%;
}
</style>
